﻿
namespace PhotoAlbum.Web.Services
{
    using System;
    using System.Data;
    using System.Linq;
    using System.ServiceModel.DomainServices.EntityFramework;
    using System.ServiceModel.DomainServices.Hosting;
    using System.ServiceModel.DomainServices.Server;
    using PhotoAlbum.Web;

    [EnableClientAccess()]
    public class PictureCommentsService : PhotoAlbumService
    {
        [Query(HasSideEffects = false, IsDefault = false)]
        public IQueryable<Comment> GetCommentsForPictureId(int pictureId)
        {
            var picture = GetViewablePicture(pictureId);
            var showCommentsPendingForApproval = this.PhotoUser != null &&
                                                    picture.Album.OwnerId == this.PhotoUser.Id;
            var result = picture
                        .Comments
                        .CreateSourceQuery() as IQueryable<Comment>;

            if (!showCommentsPendingForApproval)
            {
                result = result.Where(c => !c.NeedsApproval);
            }

            return result.OrderByDescending(c => c.DateCreated);
        }

        [RequiresAuthentication]
        [Query(HasSideEffects = false)]
        public IQueryable<Comment> GetCommentsForApproval()
        {
            return this.PhotoUser
                    .Albums
                    .CreateSourceQuery()
                    .SelectMany(a => a.Pictures)
                    .SelectMany(p => p.Comments)
                    .Where(c => c.NeedsApproval)
                    .OrderByDescending(c => c.DateCreated);
        }

        [RequiresAuthentication]
        public void InsertComment(Comment comment)
        {
            var picture = this.GetViewablePicture(comment.PictureId);
            if (picture.Album.CommentsPolicy == CommentsPolicy.NoComments)
            {
                throw new Exception("Comments are not allowed for this album.");
            }
            if (picture.Album.CommentsPolicy == CommentsPolicy.CommentsNeedApproval)
            {
                comment.NeedsApproval = true;
            }

            comment.DateCreated = DateTime.Now;
            comment.Author = this.PhotoUser;

            if ((comment.EntityState != EntityState.Detached))
            {
                this.ObjectContext.ObjectStateManager.ChangeObjectState(comment, EntityState.Added);
            }
            else
            {
                this.ObjectContext.Comments.AddObject(comment);
            }
        }

        [RequiresAuthentication]
        public void UpdateComment(Comment currentComment)
        {
            var original = this.ChangeSet.GetOriginal(currentComment);
            var picture = this.GetViewablePicture(original.PictureId);
            if (picture.Album.CommentsPolicy != CommentsPolicy.AllowComments)
            {
                throw new Exception("Comments are not allowed for this album.");
            }
            if(original.PictureId != currentComment.PictureId)
            {
                throw new Exception("Cannot change the target of a comment.");
            }
            if(original.AuthorId != currentComment.AuthorId)
            {
                throw new Exception("The author of a comment cannot be changed.");
            }
            if(original.AuthorId != this.PhotoUser.Id)
            {
                throw new Exception("Only the author of a comment can change its contents.");
            }
            if (original.NeedsApproval != currentComment.NeedsApproval
                && picture.Album.OwnerId != this.PhotoUser.Id )
            {
                throw new Exception("Only the owner of an album can change the approval status of an album.");
            }
            this.ObjectContext.Comments.AttachAsModified(currentComment, original);
        }

        [RequiresAuthentication]
        public void DeleteComment(Comment comment)
        {
            var original = this.ChangeSet.GetOriginal(comment);
            var picture = this.GetViewablePicture(original.PictureId);
            
            if (original.AuthorId != this.PhotoUser.Id
                && original.AuthorId != picture.Album.OwnerId)
            {
                throw new Exception("A comment can be deleted only by its author and the owner of an album.");
            }

            if ((comment.EntityState == EntityState.Detached))
            {
                this.ObjectContext.Comments.Attach(comment);
            }
            this.ObjectContext.Comments.DeleteObject(comment);
        }
    }
}


